package com.xt.base.reflection;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import com.xt.base.reflection.UV.Fuple;

public class Simple {
	
	private Simple(){}
	
	public static boolean is(Class clazz){
		return clazz.isPrimitive() || Apply.any(wrapedTypes, clazz);
	}
	
	public static boolean is(Object obj){
		return is(obj.getClass());
	}
	
	public static Set<Fuple<Class, Class, String, Object>> fuples(){
		Set<Fuple<Class, Class, String, Object>> 
			res = new HashSet<Fuple<Class, Class, String, Object>>();
		for(int i = 0;i<types.length;i++)res.add(getFuple(i));
		return res;
	}
	
	public static Fuple<Class, Class, String, Object> fuple(Class clazz){
		int i = index(clazz);
		return i != -1?getFuple(i):null;
	}
	
	public static Fuple<Class, Class, String, Object> fuple(Object obj){
		int i = index(obj.getClass());
		return i != -1?getFuple(i):null;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T valueOf(Class<T> clazz,Object ov){
		try{
			int i = index(clazz);
			if( i != -1){
				if(wrapedTypes[i].isInstance(ov))return (T)ov;
				return (T)getValueOf(i).invoke(wrapedTypes[i], String.valueOf(ov));
			}
			throw new IllegalArgumentException("[" + clazz + "]index outof:" + i);
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
	
	private static Fuple<Class, Class, String, Object> getFuple(int i){
		if(i > -1 && i < types.length){
			 return new Fuple<Class, Class, String, Object>(types[i],wrapedTypes[i],names[i],defaultValues[i]);
		}
		throw new IllegalArgumentException("index outof:" + i);
	}
	
	public static final Class<?>[] types = new Class<?>[]{char.class,boolean.class,byte.class,
		int.class,double.class,float.class,long.class,short.class};
	public static final Class<?>[] wrapedTypes = new Class<?>[]{Character.class,Boolean.class,Byte.class,
		Integer.class,Double.class,Float.class,Long.class,Short.class};
	public static final String[] names = new String[]{"char","boolean","byte","int","double","float","long","short"};
	public static final Object[] defaultValues = new Object[]{Character.MAX_VALUE,Boolean.FALSE,Byte.MAX_VALUE,
		Integer.MAX_VALUE,Double.MAX_VALUE,Float.MAX_VALUE,Long.MAX_VALUE,Short.MAX_VALUE};
	private static final Method[] valueOf = new Method[]{null,null,null,null,null,null,null,null};
	private static Method isInstance = null;
	
	private static int index(Class clazz){
		int i = Apply.indexOf(types, clazz);
		return i != -1?i:Apply.indexOf(wrapedTypes, clazz);
	}
	
	private static Class[] args1 = new Class[]{Object.class},args2 = new Class[]{String.class};
	public static Method getIsInstance(){
		try{
			if(isInstance == null)
				isInstance = Character.class.getClass().getMethod("isInstance", args1);
			return isInstance;
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
	private static Method getValueOf(int i){
		Method res = null;
		if(i > 0 && i < types.length){
			try{
				if(valueOf[i] == null)
					valueOf[i] = wrapedTypes[i].getMethod("valueOf", args2);
				res = valueOf[i];
			}catch(Exception e){
				throw new RuntimeException(e);
			}
		}
		return res;
	}
}
